package com.easylinkin.linkappapi.elasticsearch.service.impl;

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.elasticsearch.entity.DateSourceEnergyRecord;
import com.easylinkin.linkappapi.elasticsearch.entity.DeviceEnergyReal;
import com.easylinkin.linkappapi.elasticsearch.entity.ESconfig;
import com.easylinkin.linkappapi.elasticsearch.entity.EsEtlStatisticModel;
import com.easylinkin.linkappapi.elasticsearch.entity.MomStatisticModel;
import com.easylinkin.linkappapi.elasticsearch.mapper.ElasticsearchRealMapper;
import com.easylinkin.linkappapi.elasticsearch.service.IEService;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * ES 银行贷后管理相关的实际操作类
 */
@Service
public class EsBankServiceImpl extends ServiceImpl<ElasticsearchRealMapper, DeviceEnergyReal>  {

    private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(EsBankServiceImpl.class);
    private static final String FORMATLOCAL = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

    private ESconfig eSconfig;

    @Autowired
    public void setESconfig(ESconfig eSconfig) {
        this.eSconfig = eSconfig;
    }

    @Autowired
    IEService eService;

    public boolean creataIndex(String indexId) {
        RestHighLevelClient hclient = eSconfig.getFactory().getRhlClient();
        boolean isAcknowledged = false;
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexId);
        try {
            XContentBuilder mapping = jsonBuilder().
                startObject().
                startObject("mappings").
                startObject("type").
                startObject("properties").
                startObject("dataTime").field("type", "date").
                endObject().
                startObject("dataSourceId").field("type", "text")
                .endObject().
                    startObject("dayEnergy").field("type", "float").
                    endObject().
                    startObject("sumEnergy").field("type", "float").
                    endObject().
                    startObject("energyKind").field("type", "text").
                    endObject().
                    endObject().
                    endObject().
                    endObject().
                    endObject();
            createIndexRequest.source(mapping);
            isAcknowledged = hclient.indices().create(createIndexRequest, RequestOptions.DEFAULT).isAcknowledged();
        } catch (Exception e) {
            LOGGER.error("创建租户id为{}的ES索引失败!" + indexId, e);
        }
        return isAcknowledged;
    }

    public boolean insertData(String indexId, List<DateSourceEnergyRecord> objecList) {
        RestHighLevelClient hclient = eSconfig.getFactory().getRhlClient();
        BulkRequest request = new BulkRequest();
        String jsonString;
        for (DateSourceEnergyRecord obj : objecList) {
            jsonString = JSON.toJSONStringWithDateFormat(obj, FORMATLOCAL);
            request.add(new IndexRequest(indexId).id(obj.getId()).type("type").source(jsonString, XContentType.JSON));
        }
        try {
            BulkResponse bulkResponse = hclient.bulk(request, RequestOptions.DEFAULT);
            if (bulkResponse.hasFailures()) {
                for (BulkItemResponse bulkItemResponse : bulkResponse) {
                    if (bulkItemResponse.isFailed()) {
                        //检索失败操作的失败
                        BulkItemResponse.Failure failure = bulkItemResponse.getFailure(); 
                        LOGGER.error("插入索引为{}id为{}ES动作失败!", failure.getIndex(), failure.getId());
                        throw new Exception();
                    }
                }
            }
        } catch (Exception e) {

            LOGGER.error("插入索引为{}的ES动作失败{}!", indexId, e);
            return false;
        }
        return true;
    }

    /**
     * 查询柱状图一年数据
     *
     * @param calcCfgId 计算配置id
     */
    public SearchResponse getEsHistogramStatistic(String projectIndex, String dataSourceId, String calcCfgId, String etlKind, String gteString, String lteString) {
        LOGGER.info("开始查询ElasticSearch 中的数据，传入的条件：projectId" + projectIndex + "--dataSourceId:" + dataSourceId
            + "--etlKind:" + etlKind + "--calcCfgId:" + calcCfgId + "--gteString:" + gteString + "--lteString:" + lteString);
        SearchResponse searchResponse = null;
        RestHighLevelClient hclient = eSconfig.getFactory().getRhlClient();
        QueryBuilder rangeQuery = QueryBuilders.rangeQuery("calcTime").lt(new Long(lteString.substring(0, 13).replaceAll("-|\\s", ""))).gte(new Long(gteString.substring(0, 13).replaceAll("-|\\s", "")));
        QueryBuilder dataSourceIdQuery = QueryBuilders.termQuery("dataSourceId", dataSourceId);
        QueryBuilder calcRuleIdQuery = QueryBuilders.termQuery("calcCfgId", calcCfgId);

        //组装ES请求数据
        SearchRequest searchRequest = new SearchRequest(projectIndex);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        QueryBuilder boolquery = QueryBuilders.boolQuery().must(rangeQuery).must(dataSourceIdQuery).must(calcRuleIdQuery);
        searchSourceBuilder.query(boolquery).sort("calcTime", SortOrder.DESC).size(10000);
        searchRequest.source(searchSourceBuilder);
        try {
            searchResponse = hclient.search(searchRequest, RequestOptions.DEFAULT);
            LOGGER.info("柱状图查询ES请求数据：" + searchRequest.toString());

        } catch (Exception e) {
            LOGGER.info("ES查询异常" + e.getMessage());
            log.error("es request  has no  response!");
        }
        return searchResponse;
    }

    /**
     * 查询解析es查询报文 索引id   以及请求返回实例
     */
    public List<DateSourceEnergyRecord> resolvingDayEnergyRecodEachDataSourceList(SearchResponse searchResponse, MomStatisticModel model) throws JsonProcessingException {
        List<DateSourceEnergyRecord> momStatisticList = new ArrayList<DateSourceEnergyRecord>();
        if (null == searchResponse) {
            return momStatisticList;
        }
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        for (SearchHit searchHit : searchHits) {
            String source = (String) searchHit.getSourceAsString();
            DateSourceEnergyRecord record = mapper.readValue(source, DateSourceEnergyRecord.class);
            record.setDayEnergy(record.getEnergyDay());
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//注意月份是MM
            try {
                record.setDataTime(simpleDateFormat.parse(record.getCalcDate()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            if (null != model) {
                record.initalMomStatisticModel(model);
            }
            momStatisticList.add(record);
        }

        return momStatisticList;
    }

    /**
     * 解析es查询报文 索引id   以及请求返回实例
     */
    public List<EsEtlStatisticModel> analysisEsHistogramStatistic(SearchResponse searchResponse) {
        List<EsEtlStatisticModel> momStatisticList = new ArrayList<EsEtlStatisticModel>();
        if (null == searchResponse) {
            LOGGER.info("ES查询结果返回的对象为空！！！！");
            return momStatisticList;
        }
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        for (SearchHit searchHit : searchHits) {
            String source = (String) searchHit.getSourceAsString();
            //jsonString转对象
            EsEtlStatisticModel record = JSONObject.parseObject(source, EsEtlStatisticModel.class);
//            重要
            record.initEtlValueAndCalcDate();
            try {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                record.setDateTime(simpleDateFormat.parse(record.getCalcDate()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            momStatisticList.add(record);
        }
        return momStatisticList;
    }

}
